package ext.acae2.document.helper;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipFile;

import wt.content.ApplicationData;
import wt.content.ContentHelper;
import wt.content.ContentHolder;
import wt.content.ContentRoleType;
import wt.content.ContentServerHelper;
import wt.doc.WTDocument;
import wt.fc.PersistenceHelper;
import wt.fc.PersistenceServerHelper;
import wt.fc.QueryResult;
import wt.fc.ReferenceFactory;
import wt.fc.collections.WTValuedHashMap;
import wt.folder.Folder;
import wt.folder.FolderEntry;
import wt.folder.FolderHelper;
import wt.inf.container.WTContainer;
import wt.inf.container.WTContainerRef;
import wt.ixb.publicforhandlers.IxbHndHelper;
import wt.lifecycle.LifeCycleHelper;
import wt.lifecycle.LifeCycleManaged;
import wt.lifecycle.State;
import wt.log4j.LogR;
import wt.pds.StatementSpec;
import wt.query.QuerySpec;
import wt.query.SearchCondition;
import wt.recent.RecentlyVisitedHelper;
import wt.util.WTException;
import wt.util.WTPropertyVetoException;
import wt.vc.VersionControlHelper;

import com.ptc.core.foundation.type.server.impl.TypeHelper;
import com.ptc.core.meta.common.TypeIdentifier;
import com.ptc.core.meta.common.TypeIdentifierHelper;

import de.innosystec.unrar.Archive;
import de.innosystec.unrar.exception.RarException;
import de.innosystec.unrar.rarfile.FileHeader;

import ext.acae2.document.bean.ProgramPackBean;
import ext.acae2.util.QueryUtil;
import ext.acae2.util.ReportExcelGenerateUtil;
import ext.acae2.util.ReportExcelGenerateUtil2007;
import ext.acae2.util.VersionUtil;
import ext.acae2.utilities.core.CSCIBA;

/**
 * @desription 工程文件包帮助类
 * @author cnie
 * @date 2013-8-6 上午10:42:40
 */
public class ProgramPackHelper {
	
	private final static Logger LOGGER = LogR.getLogger(ProgramPackHelper.class.getName());
	
	private final static String WP_TYPE="WCTYPE|com.ptc.windchill.wp.WorkPackage|com.acae.programPack";
	private final static String PROGRAM_DOC_TYPE="WCTYPE|wt.doc.WTDocument|com.acae.programDoc";
	public final static String LIB_NAME="CJ-1000AX协同区";
	public final static String IBA_SECRET_LEVEL="SecretLevel";
	public final static String IBA_FILE_NMUBER="fileNumber";//文件号
	public final static String IBA_VERION_SEQ="versionSeq";//版次
	public final static String IBA_SEND_DATE="sendDate";//发放时间
	public final static String IBA_SEND_DEPT="sendDept";//发放单位
	public final static String IBA_WORK_DEPT="AuthorDepartment";//编制单位
	
	public final static String SUB_FOLDER_NAME="工程文件/数据接收区";
	public final static String A_FOLDER_NAME="A类文件";
	public final static String B_FOLDER_NAME="B类文件";
	
	
	public static String parseZipFile(File serverZipFile,File unZiptempFolder) throws Exception{
		String xlsFileName = null;
		ZipFile zipFile = new ZipFile(serverZipFile);
		
		try{
			Enumeration<?> entries = zipFile.getEntries();

			while (entries.hasMoreElements()) {
				ZipEntry entry = (ZipEntry) entries.nextElement();
				if (entry.isDirectory())
					continue;
				String entryName = entry.getName(); // zip文件下名称，如果包含子目录就是：目录/文件名称

				LOGGER.info("entryName before>>>>>>>>>>" + entryName);
				if (entryName.lastIndexOf("/") > -1) {
					entryName = entryName.substring(entryName.lastIndexOf("/") + 1);
				}
				LOGGER.info("entryName after>>>>>>>>>>" + entryName);
				String entryPath = unZiptempFolder.getAbsolutePath()
						+ File.separator + entryName;
				if (entryName.endsWith(".xls") || entryName.endsWith(".xlsx")) {
					xlsFileName = entryPath;
				}
				BufferedInputStream inputStream =null;
				BufferedOutputStream outputStream = null;
				try{
					inputStream = new BufferedInputStream(
							zipFile.getInputStream(entry));
					outputStream = new BufferedOutputStream(
							new FileOutputStream(entryPath));
					int character = inputStream.read();
					while (character != -1) {
						outputStream.write(character);
						character = inputStream.read();
					}
				}catch(Exception e){
					e.printStackTrace();
				}finally{
					if(outputStream!=null){
						outputStream.flush();
						outputStream.close();
					}
					if(inputStream!=null)
						inputStream.close();
				}
			}
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			if(zipFile!=null)
				zipFile.close();
		}
		return xlsFileName;
	}
	
	
	
	public static String parseRarFile(File serverRarFile,File unZiptempFolder) throws Exception{
		
		Archive rarFile = new Archive(serverRarFile);
		String xlsFileName =null;
		try{
			FileHeader fh =null;
			do{
				fh = rarFile.nextFileHeader();
				if(fh!=null){
					if(!fh.isDirectory()){
						String compressFileName = fh.getFileNameString().trim();
						if (compressFileName.lastIndexOf("\\") > -1) {
							compressFileName = compressFileName.substring(compressFileName.lastIndexOf("\\") + 1);
						}
						FileOutputStream fos =null;
						String destFileName = unZiptempFolder.getAbsolutePath()
								+ File.separator + compressFileName;
						try{
							fos = new FileOutputStream(new File(destFileName));
							rarFile.extractFile(fh, fos);
							if (compressFileName.endsWith(".xls") || compressFileName.endsWith(".xlsx")) {
								xlsFileName = destFileName;
							}
						}catch(Exception e){
							throw e;
						}finally{
							if(fos!=null)
								fos.close();
						}
					}
				}
			}while(fh!=null);
		}catch(Exception e){
			e.printStackTrace();
			throw e;
		}finally{
			if(rarFile!=null)
				rarFile.close();
		}
		
		
		
		return xlsFileName;
			
	}
	/**
	 * 
	 * @description 解析上传的xls文件并且解压zip包，返回xls在服务器的绝对路径
	 * @author cnie
	 * @date 2013-8-6 下午5:42:22
	 * @version 1.0
	 * @param request
	 * @param programtempFolder
	 * @return
	 * @throws Exception
	 */
	public static String parseUploadFile(HttpServletRequest request,File programtempFolder)throws Exception{

		
		File serverZipFile = null;
		ServletFileUpload upload = new ServletFileUpload(
				new DiskFileItemFactory());
		List<DiskFileItem> items = upload.parseRequest(request);
		for (DiskFileItem item : items) {
			if (!item.isFormField()) {
				String fileName = item.getName();
				serverZipFile = new File(programtempFolder, fileName);
				item.write(serverZipFile);
				break;
			}
		}
		File programUnZipFolder = new File(programtempFolder, "afterUnzip"); // 解压后文件夹存储目录
		if (!programUnZipFolder.exists())
			programUnZipFolder.mkdirs();
		String xlsFileName =null;
		if(serverZipFile==null)
			return xlsFileName;
		else{
			if(serverZipFile.getName().endsWith(".zip"))
				xlsFileName = parseZipFile(serverZipFile, programUnZipFolder);
			else if(serverZipFile.getName().endsWith(".rar"))
				xlsFileName = parseRarFile(serverZipFile,programUnZipFolder);
		}
		
		return xlsFileName;
	}
	
	
	/**
	 * 
	 * @description 创建工程文件包
	 * @author cnie
	 * @date 2013-8-6 上午11:43:57
	 * @version 1.0
	 * @param programPackBean
	 * @param secondFile
	 * @throws WTException
	 * @throws WTPropertyVetoException 
	 */
	public static void createProgramDoc(ProgramPackBean programPackBean,File secondFile,StringBuffer errorSb,QueryResult exitDocQr,WTContainerRef containerRef) throws Exception{
		
		//exitDocQr.reset();
		
		String programPackName = programPackBean.getProgramPackName();
		
		String sendDept = programPackBean.getSendDept();
		
		String secretLevel = programPackBean.getSecretLevel();
		
		String folderName = "/Default/"+sendDept+"/"+SUB_FOLDER_NAME+"/";
		if("普通商密".equals(secretLevel)){
			folderName = folderName+B_FOLDER_NAME;
		}else if("核心商密".equals(secretLevel)){
			folderName = folderName+A_FOLDER_NAME;
		}
		
//		WTDocument exitDoc=null;
//		while(exitDocQr.hasMoreElements()){
//			Object obj  = exitDocQr.nextElement();
//			if(!(obj instanceof WTDocument))
//				continue;
//			WTDocument doc=(WTDocument)obj;
//			String docType = TypeIdentifierHelper.getType(doc).toExternalForm();
//			if(doc.getName().equalsIgnoreCase(programPackName.trim())&&ProgramPackHelper.PROGRAM_DOC_TYPE.indexOf(docType)>-1){
//				exitDoc=doc;
//				break;
//			}
//		}
//		if(exitDoc!=null){
//			String exitDocFolderPath = FolderHelper.getFolder(exitDoc).getFolderPath();
//			if(folderName.equals(exitDocFolderPath))
//				errorSb.append("第 "+programPackBean.getRowNum()+" 行，名称：\""+programPackBean.getProgramPackName()+"\" 工程文件在系统中已存在，跳过处理<br/>");
//			else{
//				Folder changeFolder = IxbHndHelper.getFolder(folderName, ((WTContainer)containerRef.getObject()).getDefaultDomainReference(), containerRef);
//				QueryResult qr = VersionControlHelper.service.allVersionsOf(exitDoc.getMaster(), false);
//				while(qr.hasMoreElements())
//					FolderHelper.service.changeFolder((FolderEntry) qr.nextElement(), changeFolder);
//				
//			    errorSb.append("第 "+programPackBean.getRowNum()+" 行，名称：\""+programPackBean.getProgramPackName()+"\" 工程文件所在的文件夹:<font style=\"color:green\">"+
//			          exitDocFolderPath.substring(exitDocFolderPath.lastIndexOf("/")+1)+"</font>已更改到:<font style=\"color:green\">"+folderName.substring(folderName.lastIndexOf("/")+1)+"</font><br/>");
//			}
//			return ;
//		}
		
		TypeIdentifier typeId = TypeHelper.getTypeIdentifier(PROGRAM_DOC_TYPE);
		WTDocument programDoc = (WTDocument) TypeHelper.newInstance(typeId);
		
		programDoc.setName(programPackName.trim());
		
		programDoc.setContainer((WTContainer) containerRef.getObject());
		
		Folder folder =null;
		try{
			folder = FolderHelper.service.getFolder(folderName,containerRef);
		}catch(Exception e){
			folder =null;
		}
		if(folder==null){
			folder = FolderHelper.service.saveFolderPath(folderName, containerRef);
		}
		if (folder != null) {
			WTValuedHashMap map = new WTValuedHashMap();
			map.put(programDoc, folder);
			FolderHelper.assignLocations(map);
		}
		VersionUtil.setVersion(programDoc, programPackBean.getVersion());
		VersionUtil.setIteration(programDoc, "1");
		programDoc = (WTDocument) PersistenceHelper.manager.save(programDoc);
		//wp = (WorkPackage) WPHelper.service.save(wp);
		
		if(programDoc instanceof LifeCycleManaged){
			LifeCycleManaged lcm = (LifeCycleManaged)programDoc;
			programDoc = (WTDocument) LifeCycleHelper.service.setLifeCycleState(lcm, State.toState("RELEASED"));
		}
		
		/*******添加附件 begin *****************/
		if(secondFile!=null&&secondFile.exists()){
			FileInputStream fis = new FileInputStream(secondFile);
			try{
				ContentHolder contentHolder = ContentHelper.service.getContents(programDoc);
				ApplicationData appData = ApplicationData.newApplicationData(programDoc);
				appData.setFileName(secondFile.getName());
				appData.setRole(ContentRoleType.PRIMARY);
				appData = ContentServerHelper.service.updateContent(contentHolder, appData, fis);
			}catch(Exception e){
				throw e;
			}finally{
				if(fis!=null)
					fis.close();
			}
		}
		/*******添加附件end *********************/
		
		/*************设置IBA属性 begin*******************/
		CSCIBA.setIBAStringValue(programDoc, IBA_SECRET_LEVEL, programPackBean.getSecretLevel());
		CSCIBA.setIBAStringValue(programDoc, IBA_FILE_NMUBER, programPackBean.getFileNumber()==null?"":programPackBean.getFileNumber());
		CSCIBA.setIBATimestampValue(programDoc, IBA_SEND_DATE, programPackBean.getSendDate());
		CSCIBA.setIBAStringValue(programDoc, IBA_SEND_DEPT, programPackBean.getSendDept());
		CSCIBA.setIBAStringValue(programDoc, IBA_WORK_DEPT, programPackBean.getEditDept());
		CSCIBA.setIBAStringValue(programDoc, IBA_VERION_SEQ, programPackBean.getVersion());
		/*************设置IBA属性 end*******************/
		//RecentlyVisitedHelper.service.addCustomStackObject(wp, "RECENT_UPDATES_TABLE");//增加到常用包中
		
		errorSb.append("第 "+programPackBean.getRowNum()+" 行，名称：\""+programPackBean.getProgramPackName()+"\" 工程文件<font style=\"color:green\">处理成功</font><br/>");
	}
	
	
	/**
	 * 
	 * @description 判断当前的工程文件包是否存在
	 * @author cnie
	 * @date 2013-8-6 下午2:35:32
	 * @version 1.0
	 * @param name
	 * @return
	 * @throws WTException
	 */
	private static WTDocument findProgramDocByName(String name) throws WTException{
		LOGGER.debug("> Start findProgramDocByName");
        LOGGER.debug("number: " + name);
        
        QuerySpec query = new QuerySpec(WTDocument.class);
        query.setAdvancedQueryEnabled(true);
        query.appendWhere(
                new SearchCondition(
                		WTDocument.class, WTDocument.NAME, SearchCondition.EQUAL, name,false), 
                new int[]{});
        QueryResult result = PersistenceHelper.manager.find((StatementSpec) query);
        
        WTDocument programDoc = null;
        
        while (result.hasMoreElements()) {
        	programDoc = (WTDocument) result.nextElement();
        	programDoc.getCabinetName();
        	String typeDoc = TypeIdentifierHelper.getType(programDoc).toExternalForm();
        	
        	LOGGER.debug(">>>>>>>>>>>>>>>>current TypeDoc>>>>>>>>>>>"+typeDoc);
        	if(PROGRAM_DOC_TYPE.indexOf(typeDoc)>-1)
        		break;
            LOGGER.debug("Found container!");
        }
        LOGGER.debug("> End findProgramDocByName");
        return programDoc;
	}
	
	/**
	 * 
	 * @description EXCEL文件读取
	 * @author cnie
	 * @date 2013-8-6 上午11:35:01
	 * @version 1.0
	 * @param filePath
	 * @return
	 * @throws Exception
	 */
	public static List<ProgramPackBean> readExcel(String filePath,StringBuffer errorSb)
			throws Exception {
		List<ProgramPackBean> programPackBeans = new ArrayList<ProgramPackBean>();
		FileInputStream xlsIs = new FileInputStream(filePath);
		if (filePath.endsWith(".xls")) {
			ReportExcelGenerateUtil rgu = new ReportExcelGenerateUtil(xlsIs);
			String sendDept = rgu.getValue(0, 0);
			if(StringUtils.isBlank(sendDept)){
				errorSb.append("第 1 行 第1列，发放单位为空,<font style=\"color:red\">处理失败</font><br/>");
				return programPackBeans;
			}
			for (int row = 2; row < rgu.getSheetRowCount(); row++) {
				String errorStr = "";
				String fileNumber = rgu.getValue(row, 0);
				String programPackName = rgu.getValue(row, 1);
				String version = rgu.getValue(row, 2);
				String secretLevel = rgu.getValue(row, 3);
				String sendDate = rgu.getValue(row, 4);
				String filePackName = rgu.getValue(row, 5);
				if(StringUtils.isBlank(programPackName)){
					errorStr = errorStr+"第 "+(row+1)+"行，名称为空";
					//errorSb.append("第 "+(row+1)+"行，名称为空<br/>");
				}
				if(StringUtils.isBlank(version)){
					if(StringUtils.isNotBlank(errorStr)){
						errorStr = errorStr+", 版次为空";
					}else{
						errorStr = errorStr+"第 "+(row+1)+"行，版次为空";
					}
				}
//				if(StringUtils.isBlank(version)){
//					errorSb.append("第 "+(row+1)+"行，版本为空<br/>");
//				}
				
				if(StringUtils.isNotBlank(errorStr)){
					errorStr = errorStr+",跳过处理<br/>";
					errorSb.append(errorStr);
					continue;
				}
				ProgramPackBean programPackBean = new ProgramPackBean(
						fileNumber, programPackName, version, secretLevel,
						null, filePackName, sendDept, "");
				programPackBean.setRowNum(row+1);
				programPackBeans.add(programPackBean);
				
			}
		} else if (filePath.endsWith(".xlsx")) {
			ReportExcelGenerateUtil2007 rgu2007 = new ReportExcelGenerateUtil2007(
					xlsIs);
			String sendDept = rgu2007.getValue(0, 0);
			if(StringUtils.isBlank(sendDept)){
				errorSb.append("第 1 行 第1列，发放单位为空,<font style=\"color:red\">处理失败</font><br/>");
				return programPackBeans;
			}
			for (int row = 2; row < rgu2007.getSheetRowCount(); row++) {
				String errorStr = "";
				String fileNumber = rgu2007.getValue(row, 0);
				String programPackName = rgu2007.getValue(row, 1);
				String version = rgu2007.getValue(row, 2);
				String secretLevel = rgu2007.getValue(row, 3);
				String sendDate = rgu2007.getValue(row, 4);
				String filePackName = rgu2007.getValue(row, 5);
				if(StringUtils.isBlank(programPackName)){
					errorStr = errorStr+"第 "+(row+1)+"行，名称为空";
				}
				
				if(StringUtils.isBlank(version)){
					if(StringUtils.isNotBlank(errorStr)){
						errorStr = errorStr+", 版次为空";
					}else{
						errorStr = errorStr+"第 "+(row+1)+"行，版次为空";
					}
				}
				
				if(StringUtils.isNotBlank(errorStr)){
					errorStr = errorStr+",跳过处理<br/>";
					errorSb.append(errorStr);
					continue;
				}
//				if(StringUtils.isBlank(filePackName)){
//					errorSb.append("第 "+(row+1)+"行，文件包为空<br/>");
//				}
//				if(StringUtils.isBlank(version)){
//					errorSb.append("第 "+(row+1)+"行，版本为空<br/>");
//				}
				ProgramPackBean programPackBean = new ProgramPackBean(
						fileNumber, programPackName, version, secretLevel,
						null, filePackName, sendDept, "");
				programPackBean.setRowNum(row+1);
				programPackBeans.add(programPackBean);
			}
		}
		return programPackBeans;
	}
	
	public static void main(String[] args) throws Exception {
		readExcel("D:\\Glaway\\商发\\工程文件包\\数据\\测试工程文件包\\606.xlsx",new StringBuffer());
	}
}
